import { css_disnone } from '../../../../../../components/DataDefine/sourceData';
import {
  add_class,
  remove_class,
} from '../../../../../element/class_operate/Func';
import { listenCssVar_mana } from '../../../../../element/css/Func/listenCssVar/classes/cla_listenCssVar_mana';
import {
  keyboardevent_specialKey_check,
  mouse_leftbotton,
} from '../../../../../element/Event/Func/keyboardEventSpecialKeyCheck';
// eslint-disable-next-line no-unused-vars
import { unit_listenEvent_mana } from '../../../../../element/Event/listenEvent_mana/Classes/cla_unit_listenEvent_mana';
import { fromToAnimaFunc } from '../../../../../element/fromToAnima';
import {
  appearElFunc,
  disappearElFunc,
  packNode,
} from '../../../../../element/Func';
import { settimeNth } from '../../../../../Func/uniFunc/Func';
import { forBindEventThis } from '../../../../Func/eventBind';
import { dragLisT_whiteSpace_mana } from '../../cla_dragList_whiteSpace_mana/Classes/cla_dragList_whiteSpace_mana';
import { vDragList_data_mana } from './cla_dragList_dataMana';

const dragList_operateTag = 'dragList_operate';

/**
 * floatEl 事件 穿透
 */
const eventEnable = 'event_enable';

const dragList_prop_eventBind = 'eventBind';

/**
 * dragList 的 spaceWhite mana
 */
const dragList_spaceWhite_manaObj = new dragLisT_whiteSpace_mana();

class dragList_operate extends vDragList_data_mana {
  get [Symbol.toStringTag]() {
    return dragList_operateTag;
  }

  /**
   * 对 列 副本 元素 进行 监控
   * @param {HTMLElement} element 指定 本体元素
   * @param {string} idprefix nthChild id 前缀
   * @param {string} attributeKey nthChild 元素 关键字 名称
   */
  constructor(element, idprefix, attributeKey, direct) {
    super(element, idprefix, attributeKey, direct);

    // 给 事件 绑定 this
    forBindEventThis(this, dragList_prop_eventBind);
  }

  /**
   * 启用 dragList 事件
   * @returns {this}
   */
  dom_for_draglist_start() {
    // 添加 ctrl down
    this.eventMana.addEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 添加 unitEl mouseDown
    this.eventMana.addEventListen(
      this.targetEl,
      'mousedown',
      this.eventBind.targetEl_nthChild_mouse_leftdown_self
    );

    return this;
  }

  /**
   * 禁用 dragList 事件
   * @returns {this}
   */
  dom_for_draglist_end() {
    // 添加 ctrl down
    this.eventMana.removeEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 添加 unitEl mouseDown
    this.eventMana.removeEventListen(
      this.targetEl,
      'mousedown',
      this.eventBind.targetEl_nthChild_mouse_leftdown_self
    );

    return this;
  }

  /**
   * 启用 drag 事件
   * @returns {this}
   */
  dom_for_drag_start() {
    // 添加 ctrl down
    this.eventMana.addEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    return this;
  }

  /**
   * 禁用 drag 事件
   * @returns {this}
   */
  dom_for_drag_end() {
    // 添加 ctrl down
    this.eventMana.removeEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    return this;
  }

  /**
   * 预备 给 ctrl 后 的 floatEl 添加一个
   * mouse move 事件 添加 事件穿透能力
   */
  floatEl_mouse_down_addEventEnable_self() {
    // 移除 自身
    this.eventMana.removeEventListen(
      this.dragLisT_floatEl,
      'mousedown',
      this.eventBind.floatEl_mouse_down_addEventEnable_self
    );

    console.log('添加 move 事件穿透 这里');

    // 添加 targetEl over nthchild 事件处理
    this.eventMana.addEventListen(
      this.targetEl,
      'mouseover',
      this.eventBind.targetEl_activeDrag_childNth_mouse_over
    );

    // 给 window 添加 一个 mouse move 为 floatEl 添加 事件穿透能力
    this.eventMana.addEventListen(
      window,
      'mousemove',
      this.eventBind.win_mouse_move_floatEl_addEventEnable_self
    );
  }

  /**
   * 给 ctrl 后 floatEl 添加 事件穿透 class
   */
  win_mouse_move_floatEl_addEventEnable_self() {
    // 移除 自身
    this.eventMana.removeEventListen(
      window,
      'mousemove',
      this.eventBind.win_mouse_move_floatEl_addEventEnable_self
    );

    console.log('事件穿透 move 这里');

    // 添加 事件 穿透
    add_class(this.dragLisT_floatEl, eventEnable);
  }

  /**
   * window 监听 ctrl 按下 事件
   * @param {KeyboardEvent} keyEvent
   */
  win_ctrl_down_self(keyEvent) {
    if (!keyboardevent_specialKey_check(keyEvent, 'Control')) {
      return;
    }

    console.log('ctrl down');

    // ctrl 重置
    this.body_AttriMana.resetDragList();

    // 移除 自身 --window  ctrl_down 事件 避免 连续 触发
    this.eventMana.removeEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 移除 window mouse up 事件  为 子元素 点击 做准备
    this.eventMana.removeEventListen(
      window,
      'mouseup',
      this.eventBind.win_mouse_up_self_end
    );

    // 移除 targetEl mousedown 事件 为 子元素 点击 做准备
    this.eventMana.removeEventListen(
      this.targetEl,
      'mousedown',
      this.eventBind.targetEl_nthChild_mouse_leftdown_self
    );

    // // 移除 targetEl mouse over 事件 线程 事件 专一
    // this.eventMana.removeEventListen(this.targetEl, 'mouseover');

    // 移除 可能 存在的 window mouse move 事件
    // this.eventMana.removeEventListen(this.dragLisT_floatEl, 'mousemove');

    // 移除 可能 存在的 floatEl mouse down 事件
    // this.eventMana.removeEventListen(this.dragLisT_floatEl, 'mousedown');

    // 添加 ctrl 后 targetEl nthChild 点击事件
    this.eventMana.addEventListen(
      this.targetEl,
      'click',
      this.eventBind.ctrl_down_targetEl_leftClick
    );

    // 添加 window key up 事件 ctrl up
    this.eventMana.addEventListen(
      window,
      'keyup',
      this.eventBind.win_ctrl_up_self
    );

    /**
     * 移除 dragLisT_floatEl 不可选区状态
     */
    remove_class(this.dragLisT_floatEl, eventEnable);

    // 显示 dragLisT_floatEl
    remove_class(this.dragLisT_floatEl, 'disnone');
  }

  /**
   * ctrl 按下 时 的 主体 元素 点击 click 选中 事件
   * @param {MouseEvent} event
   */
  ctrl_down_targetEl_leftClick(event) {
    if (!mouse_leftbotton(event)) {
      return;
    }
    console.log('ctrl 按下 时 的 主体 元素 点击 click 选中 事件');

    // 当前 点击 元素的 keyVal 关键字
    let curKeyVal = this.getEventTarget_keyVal(event.target);

    if (curKeyVal == undefined) {
      return;
    }

    // 添加 dragData 拖拽 信息
    this.body_AttriMana.dragData = curKeyVal;

    // 当前 点击 元素的 spacename
    let curFrom_spacename = this.spacenameCb(event.target);

    // 同时 只受理 一个
    if (['', undefined].includes(this.body_AttriMana.dragFrom)) {
      this.body_AttriMana.dragFrom = curFrom_spacename;
    }
  }

  /**
   * window ctrl 抬起 事件
   * @param {KeyboardEvent} keyboardEvent
   */
  win_ctrl_up_self(keyboardEvent) {
    if (!keyboardevent_specialKey_check(keyboardEvent, 'Control')) {
      return;
    }

    /**
     * 修订 逻辑
     */
    /**
     * 选中 所有的 元素
     * 取消 事件
     */
    if (this.body_AttriMana.dragData.length == this.targetData.length) {
      return;
    }

    // console.log('window ctrl 抬起 事件');

    // 移除 自身
    this.eventMana.removeEventListen(
      window,
      'mouseup',
      this.eventBind.win_ctrl_up_self
    );

    // 移除 ctrl 按下 targetEl nthChild click 事件
    this.eventMana.removeEventListen(
      this.targetEl,
      'click',
      this.eventBind.ctrl_down_targetEl_leftClick
    );

    // 添加 win key down ctrl 事件
    this.eventMana.addEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 添加 floatEl 按下 临时 事件
    this.eventMana.addEventListen(
      this.dragLisT_floatEl,
      'mousedown',
      this.eventBind.floatEl_mouse_down_addEventEnable_self
    );

    // 添加 floatEl 按下 应用动画
    this.eventMana.addEventListen(
      this.dragLisT_floatEl,
      'mousedown',
      this.eventBind.win_ctrl_down_up_floatEl_mouse_down_self
    );

    // 添加 win mouse up
    this.eventMana.addEventListen(
      window,
      'mouseup',
      this.eventBind.win_mouse_up_self_end
    );
  }

  /**
   * 2.0 主体 子元素 按下 事件
   * @param {MouseEvent} event
   */
  targetEl_nthChild_mouse_leftdown_self(event) {
    // console.log('2.0 鼠标按下');
    if (!mouse_leftbotton(event)) {
      return;
    }
    // console.log('左键按下');

    /**
     * 逻辑 修订
     */
    /**
     * 1.0 当前 元素 是 唯一的元素
     * 取消 当前 行为
     */
    if (this.targetData.length == 1) {
      return;
    }

    let curKeyVal = this.getEventTarget_keyVal(event.target);

    if (curKeyVal == undefined) {
      return;
    }

    // 移除 本身
    this.eventMana.removeEventListen(
      this.targetEl,
      'mousedown',
      this.eventBind.targetEl_nthChild_mouse_leftdown_self
    );

    // 移除 win keydown ctrl
    this.eventMana.removeEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 添加 dragData 拖拽 信息
    this.body_AttriMana.dragData = curKeyVal;

    // 获取 当前 点击 元素的 spacename
    // let curFrom_spacename = this.spacenameCb(event.target);

    // 添加 dragFrom 所属空间 信息
    this.body_AttriMana.dragFrom = this.spacenameCb(event.target);

    // 添加 mouse leave 离开主体 事件
    this.eventMana.addEventListen(
      this.targetEl,
      'mouseleave',
      this.eventBind.targetEl_mouse_down_mouse_leave
    );

    // 移除 enable class
    remove_class(this.dragLisT_floatEl, eventEnable);

    // 添加 floatEl 按下 临时 事件
    this.eventMana.addEventListen(
      this.dragLisT_floatEl,
      'mousedown',
      this.eventBind.floatEl_mouse_down_addEventEnable_self
    );

    // // 添加 win mouse up
    // this.eventMana.addEventListen(
    //   window,
    //   'mouseup',
    //   this.eventBind.win_mouse_up_self_end
    // );

    /**
     * 逻辑 修订
     */
    /**
     * win mouse up 断触 临时事件
     * 在 消失 动画时  断触 返回 当前 的 virtualData 顺序 dom 信息结构
     */
    this.eventMana.addEventListen(
      window,
      'mouseup',
      this.eventBind.temp_win_mouse_up_timeself
    );

    // 初始 元素 零点 位置
    let cssvarObj = new listenCssVar_mana(this.dragLisT_floatEl);

    cssvarObj.setCssVar(
      '--top',
      event.currentTarget.parentNode.offsetTop + 'px'
    );
    cssvarObj.setCssVar(
      '--left',
      event.currentTarget.parentNode.offsetLeft + 'px'
    );

    // 模拟 移入 点击 (window)移动 事件
    this.dragLisT_floatEl.dispatchEvent(new MouseEvent('mouseenter'));

    this.dragLisT_floatEl.dispatchEvent(
      new MouseEvent('mousedown', {
        clientX: 35,
        clientY: 35,
      })
    );

    window.dispatchEvent(
      new MouseEvent('mousemove', {
        clientX: event.pageX,
        clientY: event.pageY,
      })
    );

    // 起始 元素
    let fromEl = this.getKeyVal_el(curKeyVal);

    // 目标元素
    let toEl = this.dragLisT_floatEl;

    // 显示 floatEl
    remove_class(this.dragLisT_floatEl, 'disnone');

    // 应用动画
    activeAnima(fromEl, toEl);

    this.afterCb = () => {
      // 将 fromEl 元素 转移到 dragLisT_floatEl 元素中
      packNode(this.dragLisT_floatEl, fromEl);
      /**
       * 逻辑 修订
       */
      /**
       * 如果 当前 点按下 元素 处于 元素 末尾
       * 模拟 鼠标 移入 最后一个元素
       */
      if (this.targetData.indexOf(curKeyVal) == this.targetData.length - 1) {
        let last_node_key = this.targetData[this.targetData.length - 2];
        let last_node = this.getKeyVal_el(last_node_key);
        this.targetEl_activeDrag_childNth_mouse_over({ target: last_node });
      }

      /**
       * 逻辑 修订
       */
      /**
       * 移除 win mouse up 断触 临时事件
       */
      this.eventMana.removeEventListen(
        window,
        'mouseup',
        this.eventBind.temp_win_mouse_up_timeself
      );

      /**
       * 添加 win mouse up 结束 事件
       */
      this.eventMana.addEventListen(
        window,
        'mouseup',
        this.eventBind.win_mouse_up_self_end
      );
    };

    let afterCb = () => {
      this.afterCb();
    };

    disappearElFunc(fromEl, this.direct, afterCb);
  }

  /**
   * 记录 toel 和 tospace 信息 mouse over Nthchild
   * 判定 信息 操作 类型
   * @param {MouseEvent} event
   */
  targetEl_activeDrag_childNth_mouse_over(event) {
    // 非 指定 子元素
    if (!this.is_unitKeyEl(event)) {
      return;
    }
    // console.log('记录 toel 和 tospace 信息 mouse over Nthchild', event);

    /**
     * uni 元素 keyVal 值
     */
    let curKeyVal = this.getEventTarget_keyVal(event.target);

    let curKeyVal_unitEl = this.getKeyVal_el(curKeyVal);

    this.setCurToNode(curKeyVal_unitEl);

    // 是否相同 的 keyValNode
    if (this.isSameToNode()) {
      // console.log(' Same Node');
      return;
    }

    this.body_AttriMana.dragToEl = curKeyVal;

    let curDragKeysArr = this.body_AttriMana.dragData;

    let curKeyVal_spacename = this.getEventTarget_spacename(event.target);

    this.body_AttriMana.dragTo = curKeyVal_spacename;

    // 不相同 的 from to spacename 不做处理
    if (!this.analysisFromToEl()) {
      return;
    }

    // 获取 第一个 from 信息 的 index 作为 from 相对标识位
    let fromElind = this.getKeyValInd(curDragKeysArr[0]);

    // 获取 toKeyVal 的 index 作为 to 相对标识位
    let toElind = this.getKeyValInd(curKeyVal);

    // 当 标识 位 相同时 不做处理
    if (fromElind == toElind) {
      return;
    }

    // console.log(`dragKey: ${curDragKeysArr[0]} .index: ${fromElind} \n
    //      toKey: ${curKeyVal} .index: ${toElind}`);

    /**
     * 是否 放置 前置
     * @type {boolean}
     */
    let isbefore = fromElind > toElind;

    dragList_spaceWhite_manaObj.displayWhiteSapceDiv(
      curKeyVal_unitEl,
      isbefore
    );

    this.changeKeyValIndexCb(curKeyVal, curDragKeysArr, isbefore);
  }

  /**
   * 在 拖拽 状态下 离开 主体元素
   * (mouseDown) targetEl mouseLeave 鼠标 离开 主体元素
   */
  targetEl_mouse_down_mouse_leave() {
    console.log('在 拖拽 状态下 离开 主体元素');

    dragList_spaceWhite_manaObj.setSpaceDiv_active(
      dragList_spaceWhite_manaObj.curDiv,
      false
    );
    this.setCurToNode(document.body);
  }

  /**
   * window mouseup 抬起 事件 事件流 结束
   * ctrl | mousedown -- 两个事件流 处理 结束
   * 用于 初始化 数据 及 播放 动画
   */
  win_mouse_up_self_end() {
    console.log('window mouseup 抬起 事件 事件流 结束');

    // 移除 自身
    this.eventMana.removeEventListen(
      window,
      'mouseup',
      this.eventBind.win_mouse_up_self_end
    );

    // 移除 本体-子元素 nthChild 移入 事件
    this.eventMana.removeEventListen(
      this.targetEl,
      'mouseover',
      this.eventBind.targetEl_activeDrag_childNth_mouse_over
    );

    // 移除 移出 本体 事件
    this.eventMana.removeEventListen(
      this.targetEl,
      'mouseleave',
      this.eventBind.targetEl_mouse_down_mouse_leave
    );

    // 模拟 移入 up 移出 事件 floatEl 移除 floatEl 影响
    remove_class(this.dragLisT_floatEl, eventEnable);

    this.dragLisT_floatEl.dispatchEvent(new MouseEvent('mouseenter'));

    this.dragLisT_floatEl.dispatchEvent(new MouseEvent('mouseup'));

    this.dragLisT_floatEl.dispatchEvent(new MouseEvent('mouseleave'));

    // 隐藏 dragLisT_floatEl 元素
    add_class(this.dragLisT_floatEl, 'disnone');

    // 应用动画
    let dragNodeArr = this.getKeyValArr_el(this.body_AttriMana.dragData);

    let activeSpaceWhiteDiv = dragList_spaceWhite_manaObj.curDiv;

    packNode(this.targetEl, dragNodeArr, true, activeSpaceWhiteDiv);

    appearElFunc(dragNodeArr, this.direct);

    // 移除 所有 空白元素
    dragList_spaceWhite_manaObj.removeAll_spaceWhiteDiv();

    // 重置 事件监听 和 信息
    // 添加 ctrl down 事件
    this.eventMana.addEventListen(
      window,
      'keydown',
      this.eventBind.win_ctrl_down_self
    );

    // 添加 targetEl mouse down 事件
    this.eventMana.addEventListen(
      this.targetEl,
      'mousedown',
      this.eventBind.targetEl_nthChild_mouse_leftdown_self
    );

    // 重置 drag data
    this.body_AttriMana.resetDragList();

    // toEl 置空
    this.setCurToNode(null);

    // 将 数据 引入 到 实际 对象中
    this.impactToTruethData();
  }

  /**
   * 在 ctrl down up 选择 拖拽 元素后
   * 给 floatEl 元素 添加 一个 按下动画
   */
  win_ctrl_down_up_floatEl_mouse_down_self() {
    console.log(
      '在 ctrl down up 选择 拖拽 元素后   * 给 floatEl 元素 添加 一个 按下动画'
    );
    // 移除 自身
    this.eventMana.removeEventListen(
      this.dragLisT_floatEl,
      'mousedown',
      this.eventBind.win_ctrl_down_up_floatEl_mouse_down_self
    );

    // 添加 主体 鼠标 按下时 离开 事件
    this.eventMana.addEventListen(
      this.targetEl,
      'mouseleave',
      this.eventBind.targetEl_mouse_down_mouse_leave
    );

    // 起始 元素
    let fromElArr = this.getKeyValArr_el(this.body_AttriMana.data);

    // 目标元素
    let toEl = this.dragLisT_floatEl;

    // 应用动画
    activeAnima(fromElArr, toEl);

    this.afterCb = () => {
      // 将 fromEl 元素 转移到 dragLisT_floatEl 元素中
      packNode(this.dragLisT_floatEl, fromElArr);
    };

    let afterCb = () => {
      this.afterCb();
    };

    disappearElFunc(fromElArr, this.direct, afterCb);
  }

  /**
   * 当 执行动画 是 鼠标 断触 触发 抬起 事件
   * 修订 anima 动画
   * 修订 disappearElFunc 的 后续 事件
   */
  win_mouse_up_self_when_anima() {
    let cur_key_arr = this.body_AttriMana.dragData;
    let cur_dom_arr = this.getKeyValArr_el(cur_key_arr);
    for (const cur_dom of cur_dom_arr) {
      let animations = cur_dom.getAnimations();
      if (animations.length > 0) {
        let anima = animations[0];
        anima.pause();
        anima.reverse();
      }
    }
  }

  /**
   * 逻辑 修订
   * 在动画 期间 如果 鼠标 抬起 则 触发 回退 取消 本次操作
   */
  temp_win_mouse_up_timeself() {
    // 获取 当前 选中 的 数据 按照 最后的 virtual 顺序 appearEl
    let cur_keys_arr = this.body_AttriMana.dragData;
    let key;
    let key_dom;
    let after_key;
    let after_node;
    for (let ind = cur_keys_arr.length - 1; ind >= 0; ind--) {
      key = cur_keys_arr[ind];
      key_dom = this.getKeyVal_el(key);

      let cur_virtual_ind = this.getKeyValInd(key);

      after_key = this.virtualData[cur_virtual_ind + 1] || undefined;

      if (after_key != undefined) {
        after_node = this.getKeyVal_el(after_key);
      }
      packNode(this.targetEl, key_dom, true, after_node);
    }

    // 由于 断触 重新 显示 上一组 数据
    cur_keys_arr.forEach((key) => {
      // this.getKeyVal_el(key).classList.add(css_disnone);
      appearElFunc(this.getKeyVal_el(key));
    });

    // 重置 drag data
    this.body_AttriMana.resetDragList();

    this.afterCb = () => {
      remove_class(this.getKeyVal_el(key), css_disnone);
      /**
       * 逻辑 修订
       */
      /**
       * 移除 win mouse up 断触 临时事件
       */
      this.eventMana.removeEventListen(
        window,
        'mouseup',
        this.eventBind.temp_win_mouse_up_timeself
      );
    };

    this.win_mouse_up_self_end();
  }
}

/**
 * 应用动画
 * @param {HTMLElement[] | HTMLElement} dragFromElArr
 * @param {HTMLElement} toEl
 */
function activeAnima(dragFromElArr, toEl) {
  if (dragFromElArr instanceof HTMLElement) {
    dragFromElArr = [dragFromElArr];
  }
  for (const ind in dragFromElArr) {
    let uniEl = dragFromElArr[ind];
    settimeNth(ind * 100, () => {
      fromToAnimaFunc(uniEl, toEl);
    });
  }
}

export { dragList_operate };
